﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AMStudio.DelegateDispather;
using AMStudio.Script;
using AMStudio.Driver;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;


namespace AMStudio.Common
{
    public partial class GeneralManager : AEventManager, IRefrenceTagProvider
    {
        //protected ExceptionManager ExManager= EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();
        protected MachineConfig myConfig = MachineConfig.Default;

        private Dictionary<string, IAutomationDriver> MyDrivers = new Dictionary<string, IAutomationDriver>();
        private Dictionary<string, DeviceConfig> MyDriversConfig = new Dictionary<string, DeviceConfig>();

        private IAutomationDriver dialTablePLC;
        public IAutomationDriver DialTablePLC
        {
            get { return dialTablePLC; }
            set { dialTablePLC = value; }
        }

        private IAutomationDriver st1HousingScanner;

        public IAutomationDriver St1HousingScanner
        {
            get { return st1HousingScanner; }
            set { st1HousingScanner = value; }
        }

        private IAutomationDriver st1ConnecterScanner;

        public IAutomationDriver St1ConnecterScanner
        {
            get { return st1ConnecterScanner; }
            set { st1ConnecterScanner = value; }
        }

        private IAutomationDriver st1Camera;

        public IAutomationDriver St1Camera
        {
            get { return st1Camera; }
            set { st1Camera = value; }
        }

        private IAutomationDriver st12Trace;
        public IAutomationDriver St12Trace
        {
            get { return st12Trace; }
            set { st12Trace = value; }
        }

        private IAutomationDriver st6ECheck;

        public IAutomationDriver St6ECheck
        {
            get { return st6ECheck; }
            set { st6ECheck = value; }
        }

        private IAutomationDriver st6Robot;

        public IAutomationDriver St6Robot
        {
            get { return st6Robot; }
            set { st6Robot = value; }
        }

        protected override void InitProcess()
        {
            try
            {
                
                InitDriver(DialTablePLC, myConfig.DialTablePLC);
                InitDriver(St1HousingScanner, myConfig.St1HousingScannerConfig);
                InitDriver(St1ConnecterScanner, myConfig.St1ConnecterScannerConfig);
                InitDriver(St1Camera, myConfig.St1CameraConfig);
                InitDriver(St6ECheck, myConfig.St6ECheckConfig);
                InitDriver(St6Robot, myConfig.St6RobotConfig);
                InitDriver(St12Trace, myConfig.St12Trace);
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }

        }
        protected override void CycleProcess()
        {
            System.Threading.Thread.Sleep(10);
        }
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (disposing)
                {
                    ExitDriver(dialTablePLC);
                    ExitDriver(St1HousingScanner);
                    ExitDriver(St1ConnecterScanner);
                    ExitDriver(St1Camera);
                    ExitDriver(St6ECheck);
                    ExitDriver(St6Robot);
                    ExitDriver(St12Trace);
                }
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }
        }

        protected Dictionary<string, StringValueList<UserInterfaceItem>> MyUIRefreshItems =
            new Dictionary<string, StringValueList<UserInterfaceItem>>();
        protected string CurrentUI = string.Empty;
        protected void RefreshUIItems(Dictionary<string, StringValueList<UserInterfaceItem>> refreshItems, bool forceRefreshWithoutValueChangeDetect)
        {
            try
            {
                int n2 = Environment.TickCount;
                foreach (StringValueList<UserInterfaceItem> itemsGroup in refreshItems.Values)
                {
                    foreach (UserInterfaceItem item in itemsGroup)
                    {
                        string resultTag = string.Empty;
                        object directResult = null;
                        bool takeNotResult = false;
                        if (item.DisplayTag.ToUpper().StartsWith("NOT"))
                        {
                            resultTag = item.DisplayTag.Remove(0, 4).Trim();
                            takeNotResult = true;
                        }
                        else
                        {
                            resultTag = item.DisplayTag;
                        }
                        try
                        {
                            if (item.Device == myConfig.DialTablePLC.HardwareName)
                            {
                                string[] displays = resultTag.Trim().Split(';');
                                if (displays.Length > 1)
                                {
                                    string r = string.Empty;
                                    foreach (string d in displays)
                                    {
                                        r += ";" + ReadPLC(dialTablePLC, d, 1).ToString();
                                    }
                                    directResult = r.Remove(0, 1);
                                }
                                else
                                {
                                    directResult = ReadPLC(dialTablePLC, resultTag, 1);
                                }   
                            }
                            else
                            {
                                directResult = MyDrivers[item.Device].ExecuteReader(resultTag.ToUpper()).Result;
                            }
                            if (!takeNotResult)
                            {
                                item.value = directResult;
                            }
                            else
                            {
                                item.value = !(bool)directResult;
                            }

                        }
                        catch (Exception ex)
                        {
                            Exception e = new Exception("item is " + item.Device + "." + item.DisplayRefreshGroup + "." + item.DisplayTag, ex);
                            ExManager.HandleException(e, "Policy");
                        }
                    }
                    if (forceRefreshWithoutValueChangeDetect)
                    {
                        SendFeedBack(itemsGroup[0].UIName + "_GROUP_REFRESH", true, itemsGroup);
                    }
                    else
                    {
                        itemsGroup.HandleValueChange((o) =>
                        {
                            SendFeedBack(itemsGroup[0].UIName + "_GROUP_REFRESH", true, itemsGroup);
                        });
                    }
                }
                n2 = Environment.TickCount - n2;
                int a = 0;
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }
        }
        protected void ActionForUIItems(UserInterfaceItem item)
        {
            if (!string.IsNullOrEmpty(item.Action.Trim()))
            {
                string[] actions = item.Action.Trim().Split(';');
                foreach (string action in actions)
                {
                    string[] actionTags = action.Split('=');
                    if (actionTags.Length > 0)
                    {
                        if ((item.Device == myConfig.DialTablePLC.HardwareName))
                        {
                            WritePLC(dialTablePLC, actionTags[0], actionTags[1]);
                        }
                        else
                        {
                            if (actionTags[0].ToUpper() == "INIT")
                            {
                                InitDriver(MyDrivers[item.Device], MyDriversConfig[item.Device]);
                            }
                            else if (actionTags[0].ToUpper() == "EXIT")
                            {
                                ExitDriver(MyDrivers[item.Device]);
                            }
                            else
                            {
                                if (actionTags.Length == 1)
                                {
                                    MyDrivers[item.Device].ExecuteReader(actionTags[0]);
                                }
                                else
                                {
                                    MyDrivers[item.Device].ExecuteReader(actionTags[0], actionTags[1]);
                                }
                            }
                        }
                    }
                }
                System.Threading.Thread.Sleep(100);
            }
        }

        protected void ActionForUIItemsValue(UserInterfaceItem item, object value)
        {
            if (!string.IsNullOrEmpty(item.Action.Trim()))
            {
                string[] actions = item.Action.Trim().Split(';');
                int i=0;
                foreach (string action in actions)
                {

                    string[] actionTags = action.Split('=');
                    if (actionTags.Length > 1)
                    {
                        if ((item.Device == myConfig.DialTablePLC.HardwareName))
                        {
                            WritePLC(dialTablePLC, actionTags[0], actionTags[1]);
                        }
                        else
                        {
                            if (actionTags[0].ToUpper() == "INIT")
                            {
                                InitDriver(MyDrivers[item.Device], MyDriversConfig[item.Device]);
                            }
                            else if (actionTags[0].ToUpper() == "EXIT")
                            {
                                ExitDriver(MyDrivers[item.Device]);
                            }
                            else
                            {
                                if (actionTags.Length == 1)
                                {
                                    MyDrivers[item.Device].ExecuteReader(actionTags[0]);
                                }
                                else
                                {
                                    MyDrivers[item.Device].ExecuteReader(actionTags[0], actionTags[1]);
                                }
                            }
                        }
                    }
                    else if (actionTags.Length == 1)
                    {
                        if ((item.Device == myConfig.DialTablePLC.HardwareName))
                        {

                            Int32 nOrignal = Int32.Parse(value.ToString());
                            int temp = nOrignal;
                            if (i==0)
                            {
                                temp = nOrignal & 0xffff; 
                            }
                            else if (i == 1)
                            {
                                temp = (nOrignal >> 16) & 0xffff;
                            }
                            WritePLC(dialTablePLC, actionTags[0], temp.ToString());
                        }
                        
                    }

                    i++;
                }
                System.Threading.Thread.Sleep(100);
            }
        }

        protected void ActionForUIItemsMouseDown(UserInterfaceItem item)
        {
            if (!string.IsNullOrEmpty(item.Action.Trim()))
            {
                string[] actions = item.Action.Trim().Split(';');
                //foreach (string action in actions)
                if (actions.Length > 0)
                {
                    string action = actions[0];
                    string[] actionTags = action.Split('=');
                    if (actionTags.Length > 0)
                    {
                        if ((item.Device == myConfig.DialTablePLC.HardwareName))
                        {
                            WritePLC(dialTablePLC, actionTags[0], actionTags[1]);
                        }
                        else
                        {
                            if (actionTags[0].ToUpper() == "INIT")
                            {
                                InitDriver(MyDrivers[item.Device], MyDriversConfig[item.Device]);
                            }
                            else if (actionTags[0].ToUpper() == "EXIT")
                            {
                                ExitDriver(MyDrivers[item.Device]);
                            }
                            else
                            {
                                if (actionTags.Length == 1)
                                {
                                    MyDrivers[item.Device].ExecuteReader(actionTags[0]);
                                }
                                else
                                {
                                    MyDrivers[item.Device].ExecuteReader(actionTags[0], actionTags[1]);
                                }
                            }
                        }
                    }
                }
            }
        }

        protected void ActionForUIItemsMouseUp(UserInterfaceItem item)
        {
            if (!string.IsNullOrEmpty(item.Action.Trim()))
            {
                string[] actions = item.Action.Trim().Split(';');
                //foreach (string action in actions)
                if (actions.Length > 1)
                {
                    string action = actions[1];
                    string[] actionTags = action.Split('=');
                    if (actionTags.Length > 0)
                    {
                        if ((item.Device == myConfig.DialTablePLC.HardwareName))
                        {
                            WritePLC(dialTablePLC, actionTags[0], actionTags[1]);
                        }
                        else
                        {
                            if (actionTags[0].ToUpper() == "INIT")
                            {
                                InitDriver(MyDrivers[item.Device], MyDriversConfig[item.Device]);
                            }
                            else if (actionTags[0].ToUpper() == "EXIT")
                            {
                                ExitDriver(MyDrivers[item.Device]);
                            }
                            else
                            {
                                if (actionTags.Length == 1)
                                {
                                    MyDrivers[item.Device].ExecuteReader(actionTags[0]);
                                }
                                else
                                {
                                    MyDrivers[item.Device].ExecuteReader(actionTags[0], actionTags[1]);
                                }
                            }
                        }
                    }
                }
            }
        }

        protected void InitDriver(IAutomationDriver driver, DeviceConfig config)
        {
            RegisterDriver(config.HardwareName, driver, config);
            driver.ExecuteReader("INIT", this, config);
        }
        protected void ExitDriver(IAutomationDriver driver)
        {
            if (MyDrivers.ContainsKey(driver.HardwareName))
            {
                EventServer.UnSubscribeEvent(driver.HardwareEvent, new ProcessingEventHandler(HandleDriveEvents));

                driver.ExecuteReader("EXIT");
            }
        }
        protected bool DriverConnectStatus(IAutomationDriver driver)
        {
            return (bool)driver.ExecuteReader("CONNECT_STATUS").Result;
        }

        protected void CheckConnectStatusAndSetError(IAutomationDriver driver, string errorCode)
        {
            if (DriverConnectStatus(driver))
            {
                if (CurrentErrors.ContainsKey(errorCode))
                {
                    WriteError(errorCode, false);
                }
            }
            else
            {
                if (!CurrentErrors.ContainsKey(errorCode))
                {
                    WriteError(errorCode, true);
                }
            }
        }

        protected void CheckConnectStatusAndSetNotReady(IAutomationDriver driver, string address)
        {
            if (!DriverConnectStatus(driver))
            {
                WritePLC(dialTablePLC, address, "false");
            }
            
        }

        private void RegisterDriver(string name, IAutomationDriver driver, DeviceConfig config)
        {
            if (MyDrivers.ContainsKey(name))
            {
                MyDrivers[name] = driver;
            }
            else
            {
                MyDrivers.Add(name, driver);
                EventServer.SubscribeEvent(config.HardwareEvent, new ProcessingEventHandler(HandleDriveEvents));
            }
            if (MyDriversConfig.ContainsKey(name))
            {
                MyDriversConfig[name] = config;
            }
            else
            {
                MyDriversConfig.Add(name, config);
            }
        }
        private void HandleDriveEvents(string eventName, object e)
        {
            StationEventArgs se = e as StationEventArgs;

            if (se.From == myConfig.DialTablePLC.HardwareName)
            {
                switch (se.Command)
                {
                    case "CONNECT":
                        DialTablePLCError = false;
                        break;
                    case "DISCONNECT":
                        DialTablePLCError = true;
                        break;
                }
            }
        }

        public string GetTagDescription(object tag)
        {
            throw new NotImplementedException();
        }
        public string GetTagString(object tag)
        {
            throw new NotImplementedException();
        }
        public void ReSetStatus(object tagGroup)
        {
            throw new NotImplementedException();
        }
        public void ReadTag(object tag)
        {
            throw new NotImplementedException();
        }
        public void WriteTag(object tag)
        {
            throw new NotImplementedException();
        }
        public void WriteTagByIndex(object tag, int Index, object value)
        {
            throw new NotImplementedException();
        }
    }
}
